package org.mybatis.generator.api.plus;

import java.io.*;

/**
 * @author wangfupeng
 */
public class MybatisUtilException {

    public static void writeCurrentServerErrorCode(String basePackage, String targetProject) {
        File file = null;
        OutputStream fileOutputStream = null;
        BufferedWriter bufferedWriter = null;
        try {
            String packageNameFolder = basePackage.replaceAll("\\.", "/");
            targetProject = targetProject.replaceAll("\\./", "");
            File folder = new File(targetProject + "/" + packageNameFolder + "/config/exception/");
            folder.mkdirs();
            file = new File(targetProject + "/" + packageNameFolder + "/config/exception/CurrentServerErrorCode.java");
            if (file.exists()) {
                return;
            }
            //如果文件不存在，则创建文件，如果已存在，则覆盖
            file.createNewFile();
            fileOutputStream = new FileOutputStream(file);
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "utf-8"));
            bufferedWriter.write("package " + basePackage + ".config.exception;\n" +
                    "\n" +
                    "/*当前系统的所有错误代码*/\n" +
                    "public class CurrentServerErrorCode {\n" +
                    "\n" +
                    "    @ErrorMessage(\"未知错误\")\n" +
                    "    public static final int UNKNOWN = 666000;\n" +
                    "\n" +
                    "    @ErrorMessage(\"参数有误\")\n" +
                    "    public static final int EXCEPTIONHANDLER_PARAM_ERROR = 666001;\n" +
                    "\n" +
                    "    @ErrorMessage(\"header里面没有传入token\")\n" +
                    "    public static final int AUTHUSERAOP_TOKEN_NOT_PASSED = 666022;\n" +
                    "\n" +
                    "    @ErrorMessage(\"传入的token解码失败\")\n" +
                    "    public static final int AUTHUSERAOP_TOKEN_DECODE_FAILED = 666023;\n" +
                    "\n" +
                    "}\n");
            bufferedWriter.write("\n");
            System.out.println("write to file success : " + file.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            MybatisUtilCommon.closeBufferWriterAndFileOutputStream(fileOutputStream, bufferedWriter);
        }
    }

    public static void writeErrorMessage(String basePackage, String targetProject) {
        File file = null;
        OutputStream fileOutputStream = null;
        BufferedWriter bufferedWriter = null;
        try {
            String packageNameFolder = basePackage.replaceAll("\\.", "/");
            targetProject = targetProject.replaceAll("\\./", "");
            File folder = new File(targetProject + "/" + packageNameFolder + "/config/exception/");
            folder.mkdirs();
            file = new File(targetProject + "/" + packageNameFolder + "/config/exception/ErrorMessage.java");

            //如果文件不存在，则创建文件，如果已存在，则覆盖
            file.createNewFile();
            fileOutputStream = new FileOutputStream(file);
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "utf-8"));
            bufferedWriter.write("package " + basePackage + ".config.exception;\n" +
                    "\n" +
                    "import java.lang.annotation.ElementType;\n" +
                    "import java.lang.annotation.Retention;\n" +
                    "import java.lang.annotation.RetentionPolicy;\n" +
                    "import java.lang.annotation.Target;\n" +
                    "\n" +
                    "\n" +
                    "/*错误代码信息说明注解*/\n" +
                    "@Target(ElementType.FIELD)\n" +
                    "@Retention(RetentionPolicy.RUNTIME)\n" +
                    "public @interface ErrorMessage {\n" +
                    "    //异常说明\n" +
                    "    String value();\n" +
                    "}\n" +
                    "\n" +
                    "\n");
            bufferedWriter.write("\n");
            System.out.println("write to file success : " + file.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            MybatisUtilCommon.closeBufferWriterAndFileOutputStream(fileOutputStream, bufferedWriter);
        }
    }

    public static void writeCurrentServerException(String basePackage, String targetProject) {
        File file = null;
        OutputStream fileOutputStream = null;
        BufferedWriter bufferedWriter = null;
        try {
            String packageNameFolder = basePackage.replaceAll("\\.", "/");
            targetProject = targetProject.replaceAll("\\./", "");
            File folder = new File(targetProject + "/" + packageNameFolder + "/config/exception/");
            folder.mkdirs();
            file = new File(targetProject + "/" + packageNameFolder + "/config/exception/CurrentServerException.java");

            //如果文件不存在，则创建文件，如果已存在，则覆盖
            file.createNewFile();
            fileOutputStream = new FileOutputStream(file);
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "utf-8"));
            bufferedWriter.write(
                    "package " + basePackage + ".config.exception;\n" +
                            "\n" +
                            "\n" +
                            "\n" +
                            "import com.fasterxml.jackson.annotation.JsonProperty;\n" +
                            "\n" +
                            "import lombok.*;\n" +
                            "import org.slf4j.Logger;\n" +
                            "import org.slf4j.LoggerFactory;\n" +
                            "\n" +
                            "import java.text.MessageFormat;\n" +
                            "import java.util.Arrays;\n" +
                            "\n" +
                            "/*自定义异常初始化*/\n" +
                            "@Data\n" +
                            "@Builder\n" +
                            "@NoArgsConstructor\n" +
                            "@AllArgsConstructor\n" +
                            "@EqualsAndHashCode(callSuper = false)\n" +
                            "public class CurrentServerException extends RuntimeException {\n" +
                            "\n" +
                            "    private static final long serialVersionUID = 1L;\n" +
                            "\n" +
                            "    private static final Logger logger = LoggerFactory.getLogger(CurrentServerException.class);\n" +
                            "\n" +
                            "    private int status;\n" +
                            "    private String message;\n" +
                            "    private Object data;\n" +
                            "    @JsonProperty(\"more info\")\n" +
                            "    private String moreInfo;\n" +
                            "\n" +
                            "    /*从@ErrorMessage中读取错误说明*/\n" +
                            "    static {\n" +
                            "        //获取类的声明字段\n" +
                            "        Arrays.stream(CurrentServerErrorCode.class.getDeclaredFields())\n" +
                            "                //遍历\n" +
                            "                .forEach(p -> {\n" +
                            "                    try {\n" +
                            "                        //获取异常的注解\n" +
                            "                        ErrorMessage annotation = p.getAnnotation(ErrorMessage.class);\n" +
                            "                        //塞入注解的值\n" +
                            "                        System.setProperty(String.valueOf(p.get(\"value\")), annotation.value());\n" +
                            "                    } catch (Exception e) {\n" +
                            "                        logger.error(\"fail to load error code:  \" + p.getName());\n" +
                            "                    }\n" +
                            "                });\n" +
                            "    }\n" +
                            "\n" +
                            "    /*初始化自定义异常*/\n" +
                            "    public CurrentServerException(int status, Object... msg) {\n" +
                            "        //从系统中取出status对应的异常信息\n" +
                            "        String message = System.getProperty(String.valueOf(status));\n" +
                            "        //如果信息非空\n" +
                            "        if (msg != null && msg.length > 0) {\n" +
                            "            //格式化异常信息\n" +
                            "            message = MessageFormat.format(message, msg);\n" +
                            "        }\n" +
                            "        //置入状态\n" +
                            "        this.status = status;\n" +
                            "        //置入异常消息\n" +
                            "        this.message = message;\n" +
                            "    }\n" +
                            "}\n");
            bufferedWriter.write("\n");
            System.out.println("write to file success : " + file.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            MybatisUtilCommon.closeBufferWriterAndFileOutputStream(fileOutputStream, bufferedWriter);
        }
    }

    public static void writeCurrentServerExceptionHandler(String basePackage, String targetProject) {
        File file = null;
        OutputStream fileOutputStream = null;
        BufferedWriter bufferedWriter = null;
        try {
            String packageNameFolder = basePackage.replaceAll("\\.", "/");
            targetProject = targetProject.replaceAll("\\./", "");
            File folder = new File(targetProject + "/" + packageNameFolder + "/config/exception/");
            folder.mkdirs();
            file = new File(targetProject + "/" + packageNameFolder + "/config/exception/CurrentServerExceptionHandler.java");

            //如果文件不存在，则创建文件，如果已存在，则覆盖
            file.createNewFile();
            fileOutputStream = new FileOutputStream(file);
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "utf-8"));
            bufferedWriter.write(
                    "package " + basePackage + ".config.exception;\n" +
                            "\n" +
                            "import java.io.IOException;\n" +
                            "import java.util.HashMap;\n" +
                            "import java.util.List;\n" +
                            "import java.util.Map;\n" +
                            "import javax.servlet.http.HttpServletResponse;\n" +
                            "import org.slf4j.Logger;\n" +
                            "import org.slf4j.LoggerFactory;\n" +
                            "import org.springframework.util.CollectionUtils;\n" +
                            "import org.springframework.stereotype.Component;\n" +
                            "import org.springframework.validation.BindException;\n" +
                            "import org.springframework.validation.BindingResult;\n" +
                            "import org.springframework.validation.FieldError;\n" +
                            "import org.springframework.validation.ObjectError;\n" +
                            "import org.springframework.web.bind.MethodArgumentNotValidException;\n" +
                            "import org.springframework.web.bind.MissingServletRequestParameterException;\n" +
                            "import org.springframework.web.bind.annotation.ControllerAdvice;\n" +
                            "import org.springframework.web.bind.annotation.ExceptionHandler;\n" +
                            "import org.springframework.web.bind.annotation.ResponseBody;\n" +
                            "import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;\n" +
                            "import org.springframework.web.servlet.ModelAndView;\n" +
                            "import org.springframework.web.servlet.view.json.MappingJackson2JsonView;\n" +
                            "import com.fasterxml.jackson.core.JsonGenerator;\n" +
                            "import com.gitee.fufu669.response.SimpleResponse;\n" +
                            "\n" +
                            "\n" +
                            "/*所有异常在controller层全部处理了。防止抛出去使服务器宕机*/\n" +
                            "@Component\n" +
                            "@ControllerAdvice\n" +
                            "@SuppressWarnings({ \"rawtypes\" })\n" +
                            "public class CurrentServerExceptionHandler {\n" +
                            "\n" +
                            "    private static final Logger logger = LoggerFactory.getLogger(CurrentServerExceptionHandler.class);\n" +
                            "\n" +
                            "    /*处理自定义异常*/\n" +
                            "    @ResponseBody\n" +
                            "    @ExceptionHandler(CurrentServerException.class)\n" +
                            "    public ModelAndView currentServerExceptionHandler(RuntimeException e, HttpServletResponse response) {\n" +
                            "        //声明实例\n" +
                            "        ModelAndView modelAndView = new ModelAndView();\n" +
                            "        //如果是自定义服务器异常\n" +
                            "        if (e instanceof CurrentServerException) {\n" +
                            "            //拿着状态\n" +
                            "            int status = ((CurrentServerException) e).getStatus();\n" +
                            "            //声明一个Jackson2JsonView\n" +
                            "            Jackson2JsonView jackson2JsonView = new Jackson2JsonView();\n" +
                            "            //声明一个hashMap\n" +
                            "            Map<String, Object> attributes = new HashMap<>(16);\n" +
                            "            //置入状态\n" +
                            "            attributes.put(\"status\", status);\n" +
                            "            //置入消息\n" +
                            "            attributes.put(\"message\", e.getMessage());\n" +
                            "            //置入空实例\n" +
                            "            attributes.put(\"data\", null);\n" +
                            "            //置入更多资料\n" +
                            "            attributes.put(\"more info\", \"\");\n" +
                            "            //置入map\n" +
                            "            jackson2JsonView.setAttributesMap(attributes);\n" +
                            "            //设置美化打印\n" +
                            "            jackson2JsonView.setPrettyPrint(true);\n" +
                            "            //置入属性\n" +
                            "            modelAndView.setView(jackson2JsonView);\n" +
                            "            //打印错误\n" +
                            "            logger.error(\"【Error】\", e);\n" +
                            "        }\n" +
                            "        //返回结果\n" +
                            "        return modelAndView;\n" +
                            "    }\n" +
                            "\n" +
                            "    /*处理绑定错误异常*/\n" +
                            "    @ResponseBody\n" +
                            "    @ExceptionHandler(BindException.class)\n" +
                            "    public ModelAndView bindExceptionHandler(BindException e, HttpServletResponse response) {\n" +
                            "        //声明实例\n" +
                            "        ModelAndView modelAndView = new ModelAndView();\n" +
                            "        //声明实例\n" +
                            "        Jackson2JsonView jackson2JsonView = new Jackson2JsonView();\n" +
                            "        //声明一个hashMap\n" +
                            "        Map<String, Object> attributes = new HashMap<>(16);\n" +
                            "        //置入状态\n" +
                            "        attributes.put(\"status\", CurrentServerErrorCode.EXCEPTIONHANDLER_PARAM_ERROR);\n" +
                            "        //置入消息\n" +
                            "        attributes.put(\"message\", \"参数有误\");\n" +
                            "        //置入空实例\n" +
                            "        attributes.put(\"data\", null);\n" +
                            "        //获取所有绑定异常\n" +
                            "        List<ObjectError> errors = e.getBindingResult().getAllErrors();\n" +
                            "        //声明实例\n" +
                            "        StringBuilder moreInfo = new StringBuilder();\n" +
                            "        //如果异常非空\n" +
                            "        if (!CollectionUtils.isEmpty(errors)) {\n" +
                            "            //添加异常\n" +
                            "            errors.stream().filter(error -> error instanceof FieldError).forEach(error -> moreInfo\n" +
                            "                    .append(((FieldError) error).getField()).append(\":\").append(error.getDefaultMessage()).append(\";\"));\n" +
                            "        }\n" +
                            "        //置入更多资料\n" +
                            "        attributes.put(\"more info\", moreInfo.toString());\n" +
                            "        //置入map\n" +
                            "        jackson2JsonView.setAttributesMap(attributes);\n" +
                            "        //设置美化打印\n" +
                            "        jackson2JsonView.setPrettyPrint(true);\n" +
                            "        //置入属性\n" +
                            "        modelAndView.setView(jackson2JsonView);\n" +
                            "        //打印异常\n" +
                            "        logger.error(\"【Error】\", e);\n" +
                            "        //返回结果\n" +
                            "        return modelAndView;\n" +
                            "    }\n" +
                            "\n" +
                            "    /*处理异常*/\n" +
                            "    @ResponseBody\n" +
                            "    @ExceptionHandler(Exception.class)\n" +
                            "    public ModelAndView exceptionHandler(Exception e, HttpServletResponse response) {\n" +
                            "        //声明实例\n" +
                            "        ModelAndView modelAndView = new ModelAndView();\n" +
                            "        //声明实例\n" +
                            "        Jackson2JsonView jackson2JsonView = new Jackson2JsonView();\n" +
                            "        //声明一个hashMap\n" +
                            "        Map<String, Object> attributes = new HashMap<>(16);\n" +
                            "        if (e instanceof Exception) {\n" +
                            "            //置入状态\n" +
                            "            attributes.put(\"status\", CurrentServerErrorCode.UNKNOWN);\n" +
                            "            //置入消息\n" +
                            "            attributes.put(\"message\", getExceptionErrorMessage(e));\n" +
                            "            //置入空实例\n" +
                            "            attributes.put(\"data\", null);\n" +
                            "            //置入更多资料\n" +
                            "            attributes.put(\"more info\", \"\");\n" +
                            "            //置入map\n" +
                            "            jackson2JsonView.setAttributesMap(attributes);\n" +
                            "            //设置美化打印\n" +
                            "            jackson2JsonView.setPrettyPrint(true);\n" +
                            "            //置入属性\n" +
                            "            modelAndView.setView(jackson2JsonView);\n" +
                            "            //打印错误\n" +
                            "            logger.error(\"【Error】\", e);\n" +
                            "        }\n" +
                            "        //返回结果\n" +
                            "        return modelAndView;\n" +
                            "    }\n" +
                            "\n" +
                            "    /*处理方法参数非法错误异常*/\n" +
                            "    @ExceptionHandler(MethodArgumentNotValidException.class)\n" +
                            "    @ResponseBody\n" +
                            "    public SimpleResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {\n" +
                            "        //获取绑定结果\n" +
                            "        BindingResult bindingResult = ex.getBindingResult();\n" +
                            "        //定义异常信息\n" +
                            "        String message = \"\";\n" +
                            "        //遍历\n" +
                            "        for (FieldError fieldError : bindingResult.getFieldErrors()) {\n" +
                            "            //添加信息\n" +
                            "            message += fieldError.getField() + fieldError.getDefaultMessage() + \", \";\n" +
                            "        }\n" +
                            "        //声明实例\n" +
                            "        SimpleResponse response = new SimpleResponse();\n" +
                            "        //设置状态\n" +
                            "        response.setStatus(CurrentServerErrorCode.EXCEPTIONHANDLER_PARAM_ERROR);\n" +
                            "        //置入消息\n" +
                            "        response.setMessage(message);\n" +
                            "        //返回结果\n" +
                            "        return response;\n" +
                            "    }\n" +
                            "\n" +
                            "    /*处理方法参数不匹配错误异常*/\n" +
                            "    @ExceptionHandler(MethodArgumentTypeMismatchException.class)\n" +
                            "    @ResponseBody\n" +
                            "    public SimpleResponse handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) {\n" +
                            "        //声明实例\n" +
                            "        SimpleResponse response = new SimpleResponse();\n" +
                            "        //设置状态\n" +
                            "        response.setStatus(CurrentServerErrorCode.EXCEPTIONHANDLER_PARAM_ERROR);\n" +
                            "        //置入消息\n" +
                            "        response.setMessage(ex.getName() + \" needs \" + ex.getRequiredType() + \", got value: \" + ex.getValue());\n" +
                            "        //返回结果\n" +
                            "        return response;\n" +
                            "    }\n" +
                            "\n" +
                            "    /*处理缺少请求参数错误异常*/\n" +
                            "    @ExceptionHandler(MissingServletRequestParameterException.class)\n" +
                            "    @ResponseBody\n" +
                            "    public SimpleResponse handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {\n" +
                            "        //声明实例\n" +
                            "        SimpleResponse response = new SimpleResponse();\n" +
                            "        //设置状态\n" +
                            "        response.setStatus(CurrentServerErrorCode.EXCEPTIONHANDLER_PARAM_ERROR);\n" +
                            "        //置入消息\n" +
                            "        response.setMessage(ex.getParameterName() + \" required but missing\");\n" +
                            "        //返回结果\n" +
                            "        return response;\n" +
                            "    }\n" +
                            "\n" +
                            "    /*从异常中提取所有信息*/\n" +
                            "    private String getExceptionErrorMessage(Exception e) {\n" +
                            "        //拿到异常\n" +
                            "        String exceptionErrorMessage = e.getMessage();\n" +
                            "        //遍历\n" +
                            "        for (StackTraceElement element : e.getStackTrace()) {\n" +
                            "            //添加异常\n" +
                            "            exceptionErrorMessage += element.toString();\n" +
                            "        }\n" +
                            "        //返回结果\n" +
                            "        return exceptionErrorMessage;\n" +
                            "    }\n" +
                            "\n" +
                            "    /*返回的实例*/\n" +
                            "    class Jackson2JsonView extends MappingJackson2JsonView {\n" +
                            "        @Override\n" +
                            "        protected void writePrefix(JsonGenerator generator, Object object) throws IOException {\n" +
                            "        }\n" +
                            "\n" +
                            "        @Override\n" +
                            "        protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {\n" +
                            "        }\n" +
                            "    }\n" +
                            "\n" +
                            "}\n");
            bufferedWriter.write("\n");
            System.out.println("write to file success : " + file.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            MybatisUtilCommon.closeBufferWriterAndFileOutputStream(fileOutputStream, bufferedWriter);
        }
    }

}
